﻿using System;
using System.Collections.ObjectModel;
using ModelingProjectLib.Interfaces;

namespace INSAwarsWPF
{
    [Serializable()]
    /** ViewModel principal pour l'application */
    public class GameViewModel : ViewModelBase
    {
        /** View qui possède le GameViewModel */
        public GameView View { get; set; }

        /** Partie en cours */
        public Partie PartieCourante { get; set; }

        /** Collection de toutes les CasesViewModel pour la carte */
        public ObservableCollection<CaseViewModel> Cases { get; private set; }

        /** Ensemble des joueurs de la partie */
        public EnsembleJoueursViewModel Joueurs { get; private set; }

        /** Crée un nouveau GameViewModel pour la fenêtre gw et la partie partie. Remplit les listes d'objets à observer */
        public GameViewModel(GameView gw, Partie partie)
        {
            View = gw;
            PartieCourante = partie;
            ModeExtensionVille = false;
            VilleAEtendre = null;
            IsPartieFinie = false;

            // important pour que les objets se mettent à jour tout seul
            Cases = new ObservableCollection<CaseViewModel>();
            Joueurs = new EnsembleJoueursViewModel(this);

            for (int i = 0; i < PartieCourante.CartePartie.Taille; i++)
            {
                for (int j = 0; j < PartieCourante.CartePartie.Taille; j++)
                {
                    CaseViewModel cvm = new CaseViewModel(this, i, j, PartieCourante.CartePartie.MatriceCases[i][j]);
                    Cases.Add(cvm);
                }
            }

            foreach (Joueur j in PartieCourante.ListJoueurs)
            {
                JoueurViewModel jvm = new JoueurViewModel(j);

                foreach (Unite unit in j.Civilisation.ListUnites)
                {
                    int ind = unit.ColumnPosition + PartieCourante.CartePartie.Taille * unit.RowPosition;

                    UniteViewModel unitVM = new UniteViewModel(Cases[ind], unit);
                    Cases[ind].Unites.Add(unitVM);
                    jvm.Unites.Add(unitVM);

                    jvm.DerniereCaseSelectionnee = Cases[ind];
                    jvm.DerniereUniteSelectionnee = unitVM;

                    if (j == PartieCourante.JoueurCourant && unit is Enseignant) {
                        // on commence la partie avec l'enseignant du premier joueur sélectionné
                        SelectedCase = Cases[ind];
                        SelectedCase.SelectedUnite = unitVM;
                    }
                }
                Joueurs.Add(jvm);

                // ne devrait pas arriver au démarrage...
                foreach (Ville ville in j.Civilisation.ListVilles)
                {
                    int ind = ville.ColumnPosition + PartieCourante.CartePartie.Taille * ville.RowPosition;

                    VilleViewModel villeVM = new VilleViewModel(Cases[ind], ville);
                    Cases[ind].VilleCase = villeVM;
                    //jvm.Villes.Add(villeVM);
                }
            }

            Joueurs.DoApresRemplissage();
        }
        
        /** Case sélectionnée sur la carte */
        private CaseViewModel selectedCase;
        public CaseViewModel SelectedCase
        {
            get { return selectedCase; }

            set
            {
                // mode extension de ville
                if (ModeExtensionVille)
                {
                    VilleAEtendre.etendre(value);
                    // même si on ne réussit pas : on enlève le mode extension de ville
                    ModeExtensionVille = false;
                    VilleAEtendre = null;
                }

                if (selectedCase != value)
                {
                    if (selectedCase != null)
                    {
                        selectedCase.SelectedUnite = null; // on déselectionne l'unité dans la case
                        selectedCase.IsSelected = false;
                    }

                    selectedCase = value;

                    if (selectedCase != null)
                    {
                        selectedCase.IsSelected = true;
                        if (View.ListBoxJeu != null) View.ListBoxJeu.ScrollIntoView(selectedCase); //marche pas au démarrage
                        if (selectedCase.HasUnite && selectedCase.SelectedUnite == null)
                        {
                            selectedCase.SelectedUnite = selectedCase.Unites[0];
                            View.focusOnSelectedUnite();
                        }
                    }

                    RaisePropertyChanged("SelectedCase");
                }
            }
        }

        /** Vrai ssi on est en mode d'extension de ville */
        public bool ModeExtensionVille { get; set; }

        /** Ville qu'on veut étendre si on est en mode d'extension de ville */
        public VilleViewModel VilleAEtendre { get; set; }

        /** Met à jour la vue après un changement de joueur */
        public void majViewChangementJoueur()
        {
            RaisePropertyChanged("SelectedCase");
        }

        /** Sélectionne l'unité suivante à qui il reste des points de mouvements */
        public void selectionnerUniteSuivante()
        {
            foreach (UniteViewModel uvm in Joueurs.JoueurCourant.Unites)
            {
                if (uvm.UniteModel.Mvt > 0 && uvm != SelectedCase.SelectedUnite)
                {
                    SelectedCase = uvm.Conteneur;
                    SelectedCase.SelectedUnite = uvm;
                    return;
                }
            }
        }

        /** Vrai ssi la partie est finie (i.e. il ne reste qu'un joueur) */
        public bool IsPartieFinie { get; set; }
    }


}
